package system

import (
	"fmt"
	"log"
	"path/filepath"
	"sort"
	"strings"
	"time"
)

// BackupClusterData 备份集群数据
func (m *Manager) BackupClusterData() error {
	// 获取所有节点
	allNodes := append(m.cfg.Cluster.Masters, m.cfg.Cluster.Nodes...)

	// 需要备份的目录
	dirsToBackup := []string{
		m.cfg.Cluster.Env["SEALOS_RUNTIME_ROOT"],
		m.cfg.Cluster.Env["SEALOS_DATA_ROOT"],
		m.cfg.Cluster.Env["CONTAINER_RUNROOT"],
		m.cfg.Cluster.Env["CONTAINER_GRAPHROOT"],
	}

	// 在每个节点上执行备份
	for _, node := range allNodes {
		// 生成备份目录名称，包含时间戳和节点IP
		backupDir := filepath.Join(m.cfg.Cluster.Data[0], "backups",
			fmt.Sprintf("backup_%s_%s", node, time.Now().Format("20060102_150405")))

		// 在远程节点创建备份目录
		if err := m.executor.RunCommand("ssh", node, "mkdir", "-p", backupDir); err != nil {
			return fmt.Errorf("在节点 %s 创建备份目录失败: %v", node, err)
		}

		// 在远程节点执行备份
		for _, dir := range dirsToBackup {
			targetDir := filepath.Join(backupDir, filepath.Base(dir))
			if err := m.executor.RunCommand("ssh", node, "cp", "-r", dir, targetDir); err != nil {
				return fmt.Errorf("在节点 %s 备份目录 %s 失败: %v", node, dir, err)
			}
		}

		// 备份配置文件
		if err := m.executor.RunCommand("ssh", node, "cp",
			m.cfg.Cluster.Env["CONTAINERS_STORAGE_CONF"],
			filepath.Join(backupDir, "storage.conf")); err != nil {
			return fmt.Errorf("在节点 %s 备份配置文件失败: %v", node, err)
		}

		// 备份 etcd 数据（仅在 master 节点执行）
		if contains(m.cfg.Cluster.Masters, node) {
			etcdBackupFile := filepath.Join(backupDir, "etcd-snapshot.db")
			if err := m.executor.RunCommand("ssh", node, "etcdctl",
				"snapshot", "save", etcdBackupFile); err != nil {
				return fmt.Errorf("在节点 %s 备份 etcd 数据失败: %v", node, err)
			}
		}
	}
	// 清理旧备份
	if err := m.CleanupOldBackups(); err != nil {
		log.Printf("警告：清理旧备份失败: %v", err)
	}

	return nil
}

// RestoreClusterData 从最新的备份恢复集群数据
func (m *Manager) RestoreClusterData() error {
	allNodes := append(m.cfg.Cluster.Masters, m.cfg.Cluster.Nodes...)

	// 需要恢复的目录
	dirsToRestore := []string{
		m.cfg.Cluster.Env["SEALOS_RUNTIME_ROOT"],
		m.cfg.Cluster.Env["SEALOS_DATA_ROOT"],
		m.cfg.Cluster.Env["CONTAINER_RUNROOT"],
		m.cfg.Cluster.Env["CONTAINER_GRAPHROOT"],
	}

	// 在每个节点上执行恢复
	for _, node := range allNodes {
		// 获取该节点的最新备份
		backupsDir := filepath.Join(m.cfg.Cluster.Data[0], "backups")
		pattern := fmt.Sprintf("backup_%s_*", node)
		files, err := filepath.Glob(filepath.Join(backupsDir, pattern))
		if err != nil {
			return fmt.Errorf("在节点 %s 查找备份目录失败: %v", node, err)
		}
		if len(files) == 0 {
			return fmt.Errorf("节点 %s 未找到可用的备份", node)
		}

		// 按时间排序，获取最新的备份
		sort.Slice(files, func(i, j int) bool {
			return files[i] > files[j]
		})
		latestBackup := files[0]

		// 停止节点上的服务
		_ = m.executor.RunCommand("ssh", node, "systemctl", "stop", "kubelet")
		_ = m.executor.RunCommand("ssh", node, "systemctl", "stop", "containerd")
		if contains(m.cfg.Cluster.Masters, node) {
			_ = m.executor.RunCommand("ssh", node, "systemctl", "stop", "etcd")
		}

		// 恢复数据
		for _, dir := range dirsToRestore {
			sourceDir := filepath.Join(latestBackup, filepath.Base(dir))
			if err := m.executor.RunCommand("ssh", node, "rm", "-rf", dir); err != nil {
				return fmt.Errorf("在节点 %s 清理目录 %s 失败: %v", node, dir, err)
			}
			if err := m.executor.RunCommand("ssh", node, "cp", "-r", sourceDir, dir); err != nil {
				return fmt.Errorf("在节点 %s 恢复目录 %s 失败: %v", node, dir, err)
			}
		}

		// 恢复配置文件
		if err := m.executor.RunCommand("ssh", node, "cp",
			filepath.Join(latestBackup, "storage.conf"),
			m.cfg.Cluster.Env["CONTAINERS_STORAGE_CONF"]); err != nil {
			return fmt.Errorf("在节点 %s 恢复配置文件失败: %v", node, err)
		}

		// 恢复 etcd 数据（仅在 master 节点执行）
		if contains(m.cfg.Cluster.Masters, node) {
			etcdBackupFile := filepath.Join(latestBackup, "etcd-snapshot.db")
			if err := m.executor.RunCommand("ssh", node, "etcdctl",
				"snapshot", "restore", etcdBackupFile); err != nil {
				return fmt.Errorf("在节点 %s 恢复 etcd 数据失败: %v", node, err)
			}
		}

		// 重启服务
		if contains(m.cfg.Cluster.Masters, node) {
			_ = m.executor.RunCommand("ssh", node, "systemctl", "start", "etcd")
		}
		_ = m.executor.RunCommand("ssh", node, "systemctl", "start", "containerd")
		_ = m.executor.RunCommand("ssh", node, "systemctl", "start", "kubelet")
	}
	return nil
}

// contains 检查切片中是否包含指定值
func contains(slice []string, item string) bool {
	for _, s := range slice {
		if s == item {
			return true
		}
	}
	return false
}

// CleanupOldBackups 清理超过7天的备份数据
func (m *Manager) CleanupOldBackups() error {
	backupsDir := filepath.Join(m.cfg.Cluster.Data[0], "backups")
	files, err := filepath.Glob(filepath.Join(backupsDir, "backup_*"))
	if err != nil {
		return fmt.Errorf("查找备份目录失败: %v", err)
	}

	// 获取7天前的时间
	cutoff := time.Now().AddDate(0, 0, -7)

	for _, file := range files {
		// 从文件名中提取时间信息
		parts := strings.Split(filepath.Base(file), "_")
		if len(parts) < 3 {
			continue
		}

		// 解析备份时间
		backupTime, err := time.Parse("20060102_150405", parts[len(parts)-1])
		if err != nil {
			continue
		}

		// 如果备份时间早于截止时间，则删除
		if backupTime.Before(cutoff) {
			if err := m.executor.RunCommand("rm", "-rf", file); err != nil {
				return fmt.Errorf("删除旧备份 %s 失败: %v", file, err)
			}
		}
	}

	return nil
}
